/*
 * @(#)DigestOutputStream.java	1.23 01/12/12
 *
 * 版权所有2002 Sun MicroSystems，Inc.保留所有权利。Sun专有/机密。使用受许可条款的约束。
 */

package java.security;

import java.io.IOException;
import java.io.EOFException;
import java.io.OutputStream;
import java.io.FilterOutputStream;
import java.io.PrintStream;
import java.io.ByteArrayOutputStream;

/**
 * 使用流经该流的比特更新关联消息摘要的透明流。
 *
 * <p>要完成消息摘要计算，请在调用此摘要输出流的<a href>WRITE</a>方法之后，对关联的消息摘要调用其中一个<code>Digest</code>方法。
 *      
 * <p>可以打开或关闭该流(请参阅<a href>on</a>)。当它打开时，调用<code>WRITE</code>会更新消息摘要。
 * 但当它关闭时，消息摘要不会更新。默认情况下，流处于打开状态。
 *
 * @see MessageDigest
 * @see DigestInputStream
 *
 * @version 1.23 01/12/12
 * @author Benjamin Renaud */

public class DigestOutputStream extends FilterOutputStream {
  
    private boolean on = true;

    /**  
     * The message digest associated with this stream.  
     */  
    protected MessageDigest digest;

    /**
     * 使用指定的输出流和消息摘要创建摘要输出流。
     *
     * @param stream the output stream.
     *
     * @param digest the message digest to associate with this stream.
     */
    public DigestOutputStream(OutputStream stream, MessageDigest digest) {
	super(stream);
	setMessageDigest(digest);
    }

    /**
     * Returns the message digest associated with this stream.
     *
     * @return the message digest associated with this stream.
     */
    public MessageDigest getMessageDigest() {
	return digest;
    }    

    /**
     * Associates the specified message digest with this stream.
     *
     * @param digest the message digest to be associated with this stream.  
     */
    public void setMessageDigest(MessageDigest digest) {
	this.digest = digest;
    }

    /**
     * 使用指定的字节更新消息摘要(如果摘要函数为ON)，并在任何情况下将该字节写入输出流。
     * 也就是说，如果摘要函数为ON(参见<a href>on</a>)，则此方法在与该流关联的消息摘要上调用<code>update</code>，
     * 并将字节<code>b</code>传递给它。然后，此方法将该字节写入输出流，阻塞，直到实际写入该字节。
     *
     * @param b the byte to be used for updating and writing to the    
     * output stream.    
     *
     * @exception IOException if an I/O error occurs.
     * 
     * @see MessageDigest#update(byte) 
     */
    public void write(int b) throws IOException {
	if (on) {
	    digest.update((byte)b);
	}
	out.write(b);
    }

    /**
     * 使用指定的子数组更新消息摘要(如果启用摘要函数)，并在任何情况下将子数组写入输出流。
     * 也就是说，如果摘要函数为ON(参见<a href>on</a>)，此方法将在与该流关联的消息摘要上调用<code>update</code>，
     * 并将子数组规范传递给它。然后，此方法将子数组字节写入输出流，直到实际写入字节为止。
     *
     * @param b 包含用于更新和写入输出流的子数组的数组。
     *
     * @param off 要更新和写入的第一个字节的<code>b</code>的偏移量。
     *
     * @param len 要从<code>b</code>更新和写入的数据的字节数，从偏移量<code>off</code>开始。
     *
     * @exception IOException if an I/O error occurs.
     * 
     * @see MessageDigest#update(byte[], int, int)
     */
    public void write(byte[] b, int off, int len) throws IOException {
	if (on) {
	    digest.update(b, off, len);
	}
	out.write(b, off, len);
    }

    /**
     * 打开或关闭摘要功能。默认设置为启用。当它打开时，调用<a href>WRITE</a>会导致更新消息摘要。
     * 但当它关闭时，消息摘要不会更新。
     *    
     * @param on true to turn the digest function on, false to turn it
     * off. 
     */
    public void on(boolean on) {
	this.on = on;
    }
	
    /**
     * 打印此摘要输出流及其关联的消息摘要对象的字符串表示形式。
     */
     public String toString() {
	 return "[Digest Output Stream] " + digest.toString();
     }
}	


  

